using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Domain.Entities.Auditing;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Yozeev.BusinessLogic;
using Yozeev.BusinessLogic.Dtos;
using Yozeev.BusinessLogic.Stats.Dtos;
using Yozeev.BusinessLogic.TicketLogic.Dtos;
using Yozeev.Common;
using Yozeev.Controllers.Stats.Detail;
using Yozeev.Controllers.Stats.Filters;
using Yozeev.Dtos;

namespace Yozeev.Controllers.Stats
{
    [Route("api/Stats/[Controller]/[Action]")]
    public class TravelAgencyController: YozeevControllerBase
    {
        private readonly IRepository<Activity, Guid> _activityRep;

        private readonly IRepository<TravelAgency, Guid> _travelAgRep;

        private readonly IRepository<TicketDetail, Guid> _ticketDetailRep;

        private readonly IRepository<Schedule, Guid> _scheduleRep;

        private readonly IRepository<TicketPrice, Guid> _ticketPriceRep;

        private readonly IRepository<ActivityDetail, Guid> _activityDetail;

        private readonly AbstractFilter _routeFilter;

        private readonly AbstractFilter _boatFilter;

        private readonly AbstractFilter _ticketTypeFilter;

        private readonly IGetDetailable _statDetail;

        private readonly IQueryHelper _queryHelper;

        public TravelAgencyController(
            IRepository<Activity, Guid> activityRep, 
            IRepository<TravelAgency, Guid> travelAgRep, 
            IRepository<TicketDetail, Guid> ticketDetailRep,
            IRepository<Schedule, Guid> scheduleRep,
            IRepository<TicketPrice, Guid> ticketPriceRep,
            IRepository<ActivityDetail, Guid> activityDetail,
            RouteFilter routeFilter,
            TicketTypeFilter ticketTypeFilter,
            BoatFilter boatFilter,
            StatDetail statDetail,
            IQueryHelper queryHelper)
        {
            _statDetail = statDetail;
            _ticketDetailRep = ticketDetailRep;
            _activityRep = activityRep;
            _queryHelper = queryHelper;
            _travelAgRep = travelAgRep;
            _scheduleRep = scheduleRep;
            _ticketDetailRep = ticketDetailRep;
            _ticketPriceRep = ticketPriceRep;
            _activityDetail = activityDetail;
            _routeFilter = routeFilter;
            _ticketTypeFilter = ticketTypeFilter;
            _boatFilter = boatFilter;
        }

        /// <summary>
        /// 旅行社售票统计
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<StatsPagedResultDto<TravelAgencyResultDto>> GetPagedStat(GetTravelAgencyInput input, string routeId, string boatId, string ticketId)
        {
            var query = _activityRep.GetAll().Where(_queryHelper.WhereExp<Activity>(input.queryData));

            if (!string.IsNullOrEmpty(routeId))
            {
                var scheduleIds = _scheduleRep.GetAll().Where(s => s.RouteId.ToString()
                .Equals(routeId)).Select(s => s.Id).ToList();
                query = query.Where(a => scheduleIds.Contains(a.ScheduleId.Value));
            }

            if (!string.IsNullOrEmpty(boatId))
            {
                var scheduleIds = _scheduleRep.GetAll().Where(s => s.BoatId.ToString()
                .Equals(boatId)).Select(s => s.Id).ToList();
                query = query.Where(a => scheduleIds.Contains(a.ScheduleId.Value));
            }

            if (!string.IsNullOrEmpty(ticketId))
            {
                var ticketPriceIds = _ticketPriceRep.GetAll()
                    .Where(t => t.TicketId.ToString().Equals(ticketId)).Select(t => t.Id).ToList();
                var activityIds = _activityDetail.GetAll()
                    .Where(a => ticketPriceIds.Contains(a.TicketPriceId))
                    .Select(a => a.ActivityId)
                    .ToList();
                query = query.Where(a => activityIds.Contains(a.Id));
            }

            var result = 
                from activity in query
                where activity.PayStatus == PayStatusEnum.PayStatusPayment || activity.PayStatus == PayStatusEnum.PayStatusRefund
                where activity.TravelAgency != null
                group activity by new { activity.TravelAgencyId, activity.PayMethodId, activity.PayStatus } into a
                select new TravelAgencyResultDto
                {
                    TravelAgency = (from agency in _travelAgRep.GetAll() where agency.Id == a.Key.TravelAgencyId select agency).FirstOrDefault(),
                    SaleCount = a.Sum(act => act.ActivityType == ActivityTypeEnum.ActivityTypePayment ? act.TotalQuantity : 0),
                    RefundCount = a.Sum(act => act.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? act.TotalQuantity : 0),
                    TotalCount = a.Sum(act => act.ActivityType == ActivityTypeEnum.ActivityTypePayment ? act.TotalQuantity : 0) - a.Sum(act => act.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? act.TotalQuantity : 0),
                    CashAmount = a.Sum(act => (act.PayMethod.PayCode == "Cash" && act.ActivityType == ActivityTypeEnum.ActivityTypePayment) ? act.TotalQuantity : 0),
                    CardAmount = a.Sum(act => (act.PayMethod.PayCode == "Card" && act.ActivityType == ActivityTypeEnum.ActivityTypePayment) ? act.TotalQuantity : 0),
                    WeiChatAmount = a.Sum(act => (act.PayMethod.PayCode == "WeiChat" && act.ActivityType == ActivityTypeEnum.ActivityTypePayment) ? act.TotalQuantity : 0),
                    ZhiFuBaoAmount = a.Sum(act => (act.PayMethod.PayCode == "ZhiFuBao" && act.ActivityType == ActivityTypeEnum.ActivityTypePayment) ? act.TotalQuantity : 0),
                    TotalAmount = a.Sum(act => act.TotalQuantity),
                    CashRefund = a.Sum(act => (act.PayMethod.PayCode == "Cash" && act.ActivityType == ActivityTypeEnum.ActivityTypeRefund) ? act.TotalQuantity : 0),
                    CardRefund = a.Sum(act => (act.PayMethod.PayCode == "Card" && act.ActivityType == ActivityTypeEnum.ActivityTypeRefund) ? act.TotalQuantity : 0),
                    WeiChatRefund = a.Sum(act => (act.PayMethod.PayCode == "WeiChat" && act.ActivityType == ActivityTypeEnum.ActivityTypeRefund) ? act.TotalQuantity : 0),
                    ZhiFuBaoRefund = a.Sum(act => (act.PayMethod.PayCode == "ZhiFuBao" && act.ActivityType == ActivityTypeEnum.ActivityTypeRefund) ? act.TotalQuantity : 0),
                    TotalRefund = a.Sum(act => act.ActivityType == ActivityTypeEnum.ActivityTypeRefund ? act.TotalQuantity : 0),
                    TotalAll = a.Sum(act => act.TotalAmount)
                };
            var count = await result.CountAsync();
            Dictionary<string, IEnumerable<object>> filters = new Dictionary<string, IEnumerable<object>>();
            _boatFilter.Decorate(filters);
            _ticketTypeFilter.Decorate(filters);
            _routeFilter.Decorate(filters);
            return new StatsPagedResultDto<TravelAgencyResultDto>(count, result.AsQueryable().PageBy(input).ToList(), filters);
        }

        /// <summary>
        /// 旅行社售票统计——详细
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<AccountDetailDto>> OrderSourceStatDetail(string travelAgencyId)
        {
            var activities = _activityRep.GetAll()
                .Where(activity => activity.TravelAgencyId.ToString() == travelAgencyId);
            return _statDetail.GetDetailByActivities(activities);
        }
    }
}
